package ch.zbw.sysventory.server.control;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import ch.zbw.sysventory.server.model.User;
import ch.zbw.sysventory.server.service.security.UserRoleService;
import ch.zbw.sysventory.server.service.security.UserService;

@Component
@Controller
public class UserController {

	@Autowired
	private UserService userService;

	@Autowired
	private UserRoleService userRoleService;

	@Autowired
	private Validator userValidator;

	@RequestMapping(value = "/myaccount", method = RequestMethod.GET)
	public ModelAndView myAccount(Model model) {
		Authentication auth = SecurityContextHolder.getContext().getAuthentication();
		if (!(auth instanceof AnonymousAuthenticationToken)) {
			User user = this.userService.getByLoginName(auth.getName());
			model.addAttribute("user", user);
		}
		return new ModelAndView("myaccount");
	}

	@RequestMapping(value = "/myaccount", method = RequestMethod.POST)
	public ModelAndView saveMyAccount(Model model, @ModelAttribute("user") User user, BindingResult result, HttpServletRequest request) throws Exception {
		user.setUserRole(this.userRoleService.get(Long.valueOf(request.getParameter("userRoleId"))));

		validatePassword(user, result, request);
		this.userValidator.validate(user, result);

		if (!result.hasErrors()) {
			this.userService.update(user);
			model.addAttribute("saved", "1");
		} else {
			user = this.userService.get(user.getId());
		}

		return new ModelAndView("myaccount");
	}

	@RequestMapping(value = "/users", method = RequestMethod.GET)
	public ModelAndView listUsers(Model model) {
		model.addAttribute("user_list", this.userService.list());
		return new ModelAndView("user_list");
	}

	@RequestMapping(value = "/user/{id}", method = RequestMethod.GET)
	public ModelAndView showUser(Model model, @PathVariable("id") String id) {
		Long userId = Long.valueOf(id);
		if (userId > 0)
			model.addAttribute("user", this.userService.get(userId));
		else
			model.addAttribute("user", this.userService.getNewUser());
		model.addAttribute("role_list", this.userRoleService.list());
		return new ModelAndView("user");
	}

	@RequestMapping(value = "/user/{id}", method = RequestMethod.POST)
	public ModelAndView saveUser(Model model, @ModelAttribute("user") User user, BindingResult result, HttpServletRequest request) throws Exception {
		user.setUserRole(this.userRoleService.get(Long.valueOf(request.getParameter("userRoleId"))));

		validatePassword(user, result, request);
		this.userValidator.validate(user, result);
		if (!result.hasErrors()) {
			if (user.getId() > 0)
				this.userService.update(user);
			else
				this.userService.save(user);
			model.addAttribute("saved", "1");
		} else {
			user = this.userService.get(user.getId());
		}
		model.addAttribute("role_list", this.userRoleService.list());
		return new ModelAndView("user");
	}

	@RequestMapping(params = "delete", method = RequestMethod.GET, value = "/user/{id}")
	public String deleteUser(Model model, @PathVariable("id") String id) {
		Long userId = Long.valueOf(id);
		this.userService.delete(userId);
		return "redirect:/users";
	}

	private void validatePassword(User user, BindingResult result, HttpServletRequest request) {
		String password1 = request.getParameter("password1");
		String password2 = request.getParameter("password2");
		if (password1 != null && password2 != null && (!"".equals(password1) || !"".equals(password2))) {
			if (!password1.equals(password2)) {
				result.reject("passwords.not.equal");
			} else {
				user.setPassword(password1);
			}
		}
	}

}
